
#import "Application.h"
#include "StateManager.h"
#include "TextureManager.h"
#include "InputManager.h"
#include "Texture.h"
#include "ProgressManager.h"

@implementation Application

- (id) initApp
{
	if (self = [super init])
	{
		//create the context
		context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
        
        if (!context || ![EAGLContext setCurrentContext:context])
		{
            [self release];
            return nil;
        }
		
		// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
		glGenFramebuffersOES(1, &defaultFramebuffer);
		glGenRenderbuffersOES(1, &colorRenderbuffer);
		glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
		glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
		glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);
		
		//glClearColor(0.5f, 0.5f, 0.5f, 1.0f);

		// Initialize OpenGL states
		glEnable(GL_BLEND);
		glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_TEXTURE_2D);
		glDisable(GL_DEPTH_TEST);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND_SRC);
        
		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &appWidth);
		glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &appHeight);
        
        [self loadState];
        
        StateManager::instance().init();
    }
	
    [[InAppPurchaseManager new] loadStore];
    
	return self;
}

-(void) setup
{
    SB::contentScale = contentScale;
    SB::SCREEN_WIDTH = appWidth;
    SB::SCREEN_HEIGHT = appHeight;
    SB::PIXWIDTH = 1.0f;
    SB::PIXHEIGHT = 1.0f;
}

- (void) update:(float) dt
{	
    [self checkMoved];
    
    StateManager::instance().update(dt);
}

- (void) setMatrixes
{
	glViewport(0, 0, appWidth, appHeight);
	
	//glClear(GL_COLOR_BUFFER_BIT);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrthof(0, appWidth, 0, appHeight, -1, 1);
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

- (void) render
{
	[self setMatrixes];
	
	StateManager::instance().render();
	
	//swap buffers
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (BOOL) resizeFromLayer:(CAEAGLLayer *)layer
{	
	// Allocate color buffer backing based on the current layer size
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
	glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &appWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &appHeight);
	
    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
	{
		NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }
    
    return YES;
}

- (void) minimize
{
    StateManager::instance().pause();
}

#define CURRENT_VERSION     1

- (void) saveState
{
    NSUserDefaults *sud = [NSUserDefaults standardUserDefaults];
    
    [sud setInteger:CURRENT_VERSION forKey:@"iVersion"];
    
    // Options
    [sud setBool:ProgressManager::instance().getSavedData().bMusic forKey:@"bMusic"];
    [sud setBool:ProgressManager::instance().getSavedData().bSfx forKey:@"bSfx"];
    [sud setBool:ProgressManager::instance().getSavedData().bGameCenter forKey:@"bGameCenter"];
    [sud setBool:ProgressManager::instance().getSavedData().bGameCenterAsked forKey:@"bGameCenterAsked"];
    
    // General Stats
    [sud setInteger:ProgressManager::instance().getSavedData().iBabiesFedMax forKey:@"iBabiesFedMax"];
    [sud setInteger:ProgressManager::instance().getSavedData().iBabiesFedTotal forKey:@"iBabiesFedTotal"];
    [sud setInteger:ProgressManager::instance().getSavedData().iCoins forKey:@"iCoins"];
    [sud setInteger:ProgressManager::instance().getSavedData().iCoinsTotal forKey:@"iCoinsTotal"];
    [sud setInteger:ProgressManager::instance().getSavedData().iCoinsSpent forKey:@"iCoinsSpent"];
    [sud setInteger:ProgressManager::instance().getSavedData().iGamesTotal forKey:@"iGamesTotal"];
    [sud setInteger:ProgressManager::instance().getSavedData().iPrizesTotal forKey:@"iPrizesTotal"];
    [sud setInteger:ProgressManager::instance().getSavedData().iChainMax forKey:@"iChainMax"];
    
    // Specific achievement data
    [sud setInteger:ProgressManager::instance().getSavedData().iLastDayPlayed forKey:@"iLastDayPlayed"];
//    [sud setInteger:ProgressManager::instance().getSavedData().iBoletsUsed forKey:@"iBoletsUsed"];
/*	
	// Shop items
    for(int i=0; i<UPGRADES_COUNT; ++i)
    {
        [sud setBool:ProgressManager::instance().getSavedData().baUpgrades[i] forKey:[NSString stringWithFormat:@"baUpgrades%i", i]];
    }

    for(int i=0; i<POWERUPS_TYPE_COUNT; ++i)
    {
        [sud setInteger:ProgressManager::instance().getSavedData().iaPowerUps[i] forKey:[NSString stringWithFormat:@"iaPowerUps%i", i]];
    }
*/   
    
    // Babies
    for(int i=0; i<MAX_BABY_TYPES; ++i)
    {
        [sud setBool:ProgressManager::instance().getSavedData().sBabyData[i].bUnlocked forKey:[NSString stringWithFormat:@"baby.bUnlocked%i", i]];
        [sud setInteger:ProgressManager::instance().getSavedData().sBabyData[i].iPrizesCollected forKey:[NSString stringWithFormat:@"baby.iPrizesCollected%i", i]];
    }
    
    // Achievements
    for(int i=0; i<MAX_ACHIEVEMENTS; ++i)
    {
        [sud setBool:ProgressManager::instance().getSavedData().sAchievementData[i].bUnlocked forKey:[NSString stringWithFormat:@"ach.bUnlocked%i", i]];
        [sud setInteger:ProgressManager::instance().getSavedData().sAchievementData[i].iProgress forKey:[NSString stringWithFormat:@"ach.iProgress%i", i]];
    }

    [sud synchronize];
}

- (void) loadState
{
    NSUserDefaults *sud = [NSUserDefaults standardUserDefaults];
    
    NSNumber *num = [sud valueForKey:@"iVersion"];
    if(num != nil && [num intValue] == CURRENT_VERSION)
    {
        ProgressManager::instance().setBabiesFedMax([[sud valueForKey:@"bMusic"] intValue]);
        ProgressManager::instance().setBabiesFedTotal([[sud valueForKey:@"getBabiesFedTotal"] intValue]);

        SaveGame sSaveGame;
        
        // Options
        sSaveGame.bMusic = [[sud valueForKey:@"bMusic"] boolValue];
        sSaveGame.bSfx = [[sud valueForKey:@"bSfx"] boolValue];
        sSaveGame.bGameCenter = [[sud valueForKey:@"bGameCenter"] boolValue];
        sSaveGame.bGameCenterAsked = [[sud valueForKey:@"bGameCenterAsked"] boolValue];
        
        // General Stats
        sSaveGame.iBabiesFedMax = [[sud valueForKey:@"iBabiesFedMax"] intValue];
        sSaveGame.iBabiesFedTotal = [[sud valueForKey:@"iBabiesFedTotal"] intValue];
        sSaveGame.iCoins = [[sud valueForKey:@"iCoins"] intValue];
        sSaveGame.iCoinsTotal = [[sud valueForKey:@"iCoinsTotal"] intValue];
        sSaveGame.iCoinsSpent = [[sud valueForKey:@"iCoinsSpent"] intValue];
        sSaveGame.iGamesTotal = [[sud valueForKey:@"iGamesTotal"] intValue];
        sSaveGame.iPrizesTotal = [[sud valueForKey:@"iPrizesTotal"] intValue];
        sSaveGame.iChainMax = [[sud valueForKey:@"iChainMax"] intValue];
        
        // Specific achievement data
        sSaveGame.iLastDayPlayed = [[sud valueForKey:@"iLastDayPlayed"] intValue];
        //sSaveGame.iBoletsUsed = [[sud valueForKey:@"iBoletsUsed"] intValue];
/*        
        // Shop items
        for(int i=0; i<UPGRADES_COUNT; ++i)
        {
            sSaveGame.baUpgrades[i] = [[sud valueForKey:[NSString stringWithFormat:@"baUpgrades%i", i]] boolValue];
        }
        
        for(int i=0; i<POWERUPS_TYPE_COUNT; ++i)
        {
            sSaveGame.iaPowerUps[i] = [[sud valueForKey:[NSString stringWithFormat:@"iaPowerUps%i", i]] intValue];
        }
*/        
        
        // Babies
        for(int i=0; i<MAX_BABY_TYPES; ++i)
        {
            sSaveGame.sBabyData[i].bUnlocked = [[sud valueForKey:[NSString stringWithFormat:@"baby.bUnlocked%i", i]] boolValue];
            sSaveGame.sBabyData[i].iPrizesCollected = [[sud valueForKey:[NSString stringWithFormat:@"baby.iPrizesCollected%i", i]] intValue];
        }
        
        // Achievements
        for(int i=0; i<MAX_ACHIEVEMENTS; ++i)
        {
            sSaveGame.sAchievementData[i].bUnlocked = [[sud valueForKey:[NSString stringWithFormat:@"ach.bUnlocked%i", i]] intValue];
            sSaveGame.sAchievementData[i].iProgress = [[sud valueForKey:[NSString stringWithFormat:@"ach.iProgress%i", i]] intValue];
        }
        
        ProgressManager::instance().setSavedData(sSaveGame);
    }
}

- (void)touchStart:(CGPoint )point
{
	InputManager::instance().setJustPressed(Vector2(point.x, point.y));
}

- (void)touchMoved:(CGPoint )point
{
	InputManager::instance().setJustMoved(Vector2(point.x, point.y));    
}

- (void)touchEnd:(CGPoint )point
{
	InputManager::instance().setJustReleased(Vector2(point.x, point.y));    
}

#define kFilteringFactor 0.1
#define kRotLimit 5
#define kCooldown 0.4

- (void) startAcceleration
{
    /*
     [[UIAccelerometer sharedAccelerometer] setUpdateInterval:(0.04f)];
     [[UIAccelerometer sharedAccelerometer] setDelegate:self];
     */
    
    motionManager = [[CMMotionManager alloc] init];
    
    if (motionManager.gyroAvailable) 
    {
        motionManager.gyroUpdateInterval = 1.0/60.0;
        [motionManager startGyroUpdates];
        fCooldown = 0;
    } 
    else 
    {
        NSLog(@"No gyroscope on device.");
        //[motionManager release];
    }
}

- (void) stopAcceleration
{
    /*
     [[UIAccelerometer sharedAccelerometer] setDelegate:nil];
     */
    
    [motionManager stopGyroUpdates];
}

- (void) checkMoved
{
    if(!motionManager.gyroAvailable)
        return;
    
    rotX = motionManager.gyroData.rotationRate.x;
    rotY = motionManager.gyroData.rotationRate.y;
    rotZ = motionManager.gyroData.rotationRate.z;
    
    //NSLog(@"X: %.2f, Y: %.2f, Z: %.2f", rotX, rotY, rotZ);
    
    if(fCooldown <= 0)
    {
        if(rotZ < -kRotLimit || rotY > kRotLimit)
        {
            InputManager::instance().setMotion(MOTION_RIGHT);
            //NSLog(@"Right");
            fCooldown = kCooldown;
        }
        else if(rotZ > kRotLimit || rotY < -kRotLimit)
        {
            InputManager::instance().setMotion(MOTION_LEFT);
            //NSLog(@"Left");
            fCooldown = kCooldown;
        }
        else if(rotX > kRotLimit)
        {
            InputManager::instance().setMotion(MOTION_DOWN);
            //NSLog(@"Down");
            fCooldown = kCooldown;
        }
        else if(rotX < -kRotLimit)
        {
            InputManager::instance().setMotion(MOTION_UP);
            //NSLog(@"Up");
            fCooldown = kCooldown;
        }
    }
    else
    {
        fCooldown -=  SB::dt;
    }
}

- (void) dealloc
{
	// Tear down GL
	if (defaultFramebuffer)
	{
		glDeleteFramebuffersOES(1, &defaultFramebuffer);
		defaultFramebuffer = 0;
	}
	
	if (colorRenderbuffer)
	{
		glDeleteRenderbuffersOES(1, &colorRenderbuffer);
		colorRenderbuffer = 0;
	}
	
	// Tear down context
	if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];
	
	[context release];
	context = nil;
	
	[super dealloc];
}

@end
